<?php

namespace Henan\ThinkSdk\utils;

/**
 * 节点工具类
 */
class NodeUtil
{
    /**
     * 获取模块下所有的控制器和方法写入到权限表
     */
    public static function get()
    {
        // 获取应用
        $apps = config('elephant.catalog.app');
        $i = 0;
        $nodes = [];
        // 解析应用目录
        foreach ($apps as $app) {
            // 获取全部控制器
            $dir = app()->getRootPath() . '/app/' . $app . '/controller';
            $controllers = self::getFiles($dir, 'php');
            $nodes[] = ['id' => $app, 'label' => $app, 'children' => $controllers];
            continue;
            foreach ($controllers as $controller) {
                // 获取控制器下所有方法名称
                $actions = self::getAction($module, $controller);
                $nodes = $actions;
                foreach ($actions as $action) {
                    $controller = str_replace('Controller', '', $controller);
                    $data[$i]['module'] = $module;
                    $data[$i]['controller'] = $controller;
                    $data[$i]['action'] = $action;
                    //将控制器以及方法入库
                    if (!empty($module) && !empty($controller) && !empty($action)) {
                        $rule_name = $module . '/' . $controller . '/' . $action;

                        $rule = db('authrule')->where('name="' . strtolower($rule_name) . '"')->find();
                        if (!$rule) {
                            $idata = array();
                            $idata['module'] = strtolower($module . '/' . $controller);
                            $idata['type'] = "1";
                            $idata['name'] = strtolower($rule_name);
                            $idata['title'] = "";
                            $idata['regex'] = "";
                            $idata['status'] = "1";
                            db('authrule')->insert($idata);
                        }
                    }
                    $i++;
                }
            }
        }
        return $nodes;
    }

    /**
     * 获取全部控制器
     */
    public static function getFiles($dir, $ext)
    {
        $tree = [];
        // 判断是否为目录
        if (!is_dir($dir)) {
            return null;
        }
        // 获取目录下的全部文件
        $fileArr = glob($dir . '/*', GLOB_NOSORT);
        foreach ($fileArr as $file) {
            // 获取名称
            $name = basename($file);
            if (is_dir($file)) {
                // 是目录
                $tree[] = ['id' => $name, 'label' => $name, 'path' => $file, 'is_parent' => true, 'children' => self::getFiles($file, $ext)];
            } else {
                // 是文件,判断是否匹配
                $fileExt = substr($name, strrpos($name, '.') + 1);
                if ($fileExt == $ext) {
                    $tree[] = ['id' => $name, 'label' => $name, 'path' => $file, 'is_parent' => false];
                }
            }
        }
        return $tree;
    }

    /**
     * 获取文件结构
     * @return void
     */
    public static function getStructure($file)
    {
        // 文件不存在
        if (!file_exists($file)) {
            return [];
        }
        // 获取文件命名空间
        $content = file_get_contents($file);
        preg_match_all("/.*?namespace.*?(.*?);/i", $content, $matches);
        $namespace = trim($matches[1][0]);
        // 生成类
        $className = '\\' . $namespace . '\\' . basename($file, '.php');
        // 反射类
        $class = new \ReflectionClass($className);
        $list = [];
        // 获取类名
        $list['name'] = $class->getName();
        // 获取父类
        $list['parent'] = $class->getParentClass() ? $class->getParentClass()->name : '';
        // 获取成员变量
        $properties = [];
        foreach ($class->getProperties() as $item) {
            // 非本类成员变量跳过
            if ($item->class != $class->getName()) {
                continue;
            }
            $properties[] = [
                // 变量名称
                'name' => $item->name,
                // 访问控制
                'access' => $item->getModifiers()
            ];
        }
        $list['properties'] = $properties;
        // 获取成员函数
        $methods = [];
        foreach ($class->getMethods() as $item) {
            // 非本类成员函数跳过
            if ($item->class != $class->getName()) {
                continue;
            }
            if ($item->name == '__construct') {
                continue;
            }
            $methods[] = [
                // 函数名称
                'name' => $item->name,
                // 函数参数
                'param' => $item->getParameters(),
                // 访问控制
                'access' => $item->getModifiers()
            ];
        }
        $list['methods'] = $methods;
        // 获取行数
        $list['line'] = [$class->getStartLine(), $class->getEndLine()];
        // 获取路径
        $list['path'] = $class->getFileName();
        return $list;
    }

    /**
     * 获取控制器下所有方法名称
     */
    protected static function getAction($module, $controller)
    {

        if (empty($controller)) {
            return null;
        }
        $customer_functions = [];
        $file = app()->getRootPath() . ' / app / ' . $module . ' / controller / ' . $controller . ' . php';
        if (file_exists($file)) {
            $content = file_get_contents($file);
            preg_match_all("/.*?public.*?function(.*?)\(.*?\)/i", $content, $matches);
            $functions = $matches[1];
            //排除部分方法
            $inherents_functions = array('_initialize', '__construct', 'getActionName', 'isAjax', 'display', 'show', 'fetch', 'buildHtml', 'assign', '__set', 'get', '__get', '__isset', '__call', 'error', 'success', 'ajaxReturn', 'redirect', '__destruct', '_empty');
            foreach ($functions as $func) {
                $func = trim($func);
                if (!in_array($func, $inherents_functions)) {
                    $customer_functions[] = $func;
                }
            }
            return $customer_functions;
        } else {
//            \ticky\Log::record('is not file ' . $file, Log::INFO);
            return false;
        }
        return null;
    }
}